//前100热门楼盘，各公司占比
package main

import (
	//"flag"
	"fmt"
	goq "lib/goquery"
	"lib/request"
	//"math"
	"os"
	"runtime"
	//"strconv"
	"strings"
	"sync"
	"time"
)

var (
	main_domain = "" //主域名
	LOG         = "anjuke_companyRate_in_hot100Community"
	NumCPU      = runtime.NumCPU()
	waitgroup   = &sync.WaitGroup{}
)

type BROKER_LIST struct {
	list  map[string]int
	mutex sync.Mutex
}

//组合combo
func (bl *BROKER_LIST) combo(str string) {
	bl.mutex.Lock()
	bl.list[str]++
	bl.mutex.Unlock()
}

func main() {
	for i := 1; i <= 10; i++ {
		url := fmt.Sprintf("http://beijing.anjuke.com/community/W0QQpZ%d", i)
		getCommunitylist(url)
	}
	s(time.Now().Format("2006-01-02 15:04:05"), "done.")
}

//读取楼盘列表
func getCommunitylist(url string) {
	doc, e := getDoc(url)
	if e != nil {
		errlog(e.Error())
		return
	}

	doc.Find(".list > .list_item .details").Each(func(i int, sec *goq.Selection) {
		var (
			district      string //区县
			block         string //板块
			communityname string //楼盘名称
			link          string //二手房源列表链接
		)
		tmp := filterStr(sec.Find("p").Eq(0).Text())
		tmp = strings.Replace(tmp, "[", "", -1)
		tmparr := strings.Split(tmp, "]")
		tmp = tmparr[0]
		tmparr = strings.Split(tmp, string([]byte{194, 160}))
		district = tmparr[0]
		block = tmparr[1]

		communityname = filterStr(sec.Find(".t_b > a").Text())
		link, ok := sec.Find("p:contains('二手房') > a").Attr("href")
		if !ok {
			return
		}
		getHouseList(link, district+"#"+block+"#"+communityname)

	})
}

//获取楼盘二手房源列表
func getHouseList(url string, str string) {
	broker_list := BROKER_LIST{
		list: make(map[string]int),
	}
	for i := 1; i <= 50; i++ {
		tmpurl := fmt.Sprintf("%s/p%d/#filtersort", url, i)
		doc, e := getDoc(tmpurl)
		if e != nil {
			errlog(e.Error())
			return
		}
		tmparr := make([]string, 0)
		doc.Find(".m-house-list > .m-rent-house").Each(func(i int, sec *goq.Selection) {
			href, ok := sec.Find("a").Attr("href")
			if ok {
				tmparr = append(tmparr, href)
			}
		})

		for j := 0; j < len(tmparr); j += NumCPU {
			for k := j; k < j+NumCPU && k < len(tmparr); k++ {
				waitgroup.Add(1)
				getHouseDetail(tmparr[j], str, &broker_list)
			}
			waitgroup.Wait()
			time.Sleep(time.Second * 3)
		}
	}

	for k, v := range broker_list.list {
		outlog(fmt.Sprintf("%s#%d", k, v))
	}
}

//获取房源详情
func getHouseDetail(url string, str string, broker_list *BROKER_LIST) {
	defer waitgroup.Done()
	doc, e := getDoc(url)
	if e != nil {
		errlog(e.Error())
		return
	}
	var (
		companyname  string //公司名称
		agentname    string //经纪人名称
		mobile_phone string //经纪人电话
	)
	companyname, ok := doc.Find(".comp_info a").Eq(0).Attr("title")
	if !ok {
		return
	}
	companyname = filterStr(companyname)
	if companyname == "" {
		return
	}

	agentname = filterStr(doc.Find("#broker_true_name").Text())
	if agentname == "" {
		return
	}

	mobile_phone = filterStr(doc.Find(".broker_tel").Text())

	key := fmt.Sprintf("%s#%s#%s#%s", str, companyname, agentname, mobile_phone)
	broker_list.combo(key)
}

//读取doc
func getDoc(url string) (*goq.Document, error) {
	res, e := request.Get(url)
	if e != nil {
		return nil, e
	}
	doc, e := goq.NewDocumentFromResponse(res)
	if e != nil {
		return nil, e
	}
	return doc, nil
}

func filterStr(str string) string {
	str = strings.Replace(str, "\r\n", "", -1)
	str = strings.Replace(str, "\r", "", -1)
	str = strings.Replace(str, "\n", "", -1)
	str = strings.Replace(str, ",", "", -1)
	str = strings.Replace(str, " ", "", -1)
	str = strings.Replace(str, "#", "", -1)
	str = strings.TrimSpace(str)
	return str
}

func s(a ...interface{}) {
	fmt.Println(a)
}

//outlog
func outlog(str string) {
	pwd, _ := os.Getwd()
	outlog := fmt.Sprintf("%s/%s_log.txt", pwd, LOG)
	file, err := os.OpenFile(outlog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
	defer file.Close()
	if err != nil {
		return
	}
	str += "\n"
	file.WriteString(str)
}

//errlog
func errlog(str string) {
	pwd, _ := os.Getwd()
	outlog := fmt.Sprintf("%s/%s_err.txt", pwd, LOG)
	file, err := os.OpenFile(outlog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
	defer file.Close()
	if err != nil {
		return
	}
	str += "\n"
	file.WriteString(str)
}

//debuglog
func debuglog(str string) {
	pwd, _ := os.Getwd()
	outlog := fmt.Sprintf("%s/%s_debug.txt", pwd, LOG)
	file, err := os.OpenFile(outlog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
	defer file.Close()
	if err != nil {
		return
	}
	str += "\n"
	file.WriteString(str)
}
